//////////////////////////////////////////////////////////////////////
//
//	Copyright 2010-2011 Rogo's Team. All Rights Reserved
//
//////////////////////////////////////////////////////////////////////
package com.rogo.update
{
	import com.rogo.events.AppUpdateEvent;
	
	import flash.desktop.Updater;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	
	import mx.core.FlexGlobals;
	
	/**
	 * 更新过程遇到错误时派发 
	 */	
	[Event(name="error", type="com.rogo.events.AppUpdateEvent")]
	
	/**
	 * 更新描述符就绪时派发 
	 */	
	[Event(name="checkResult", type="com.rogo.events.AppUpdateEvent")]
	
	/**
	 * 程序更新辅助类
	 * 
	 * <pre>
	 * var updater:UpdateUtil = new UpdateUtil(updateURL);
	 * 
	 * 使用updater.checkVersion()进行版本检查
	 * 
	 * 版本检查结束后使用updater.update()进行程序更新
	 * 
	 * </pre>
	 * 
	 * @author rogo
	 */	
	public class AppUpdater extends EventDispatcher
	{
		public function AppUpdater(url:String = null)
		{
			updateURL = url;
		}
		
		//--------------------------------------------------------------------------
		//
		//  Variables
		//
		//--------------------------------------------------------------------------
		
		/**
		 * 更新地址 
		 */		
		public var updateURL:String;
		
		/**
		 * 当前版本号 
		 */		
		public var curVersionNumber:String;
		
		/**
		 * 当前版本符
		 */		
		public var curVersionLable:String;
		
		/**
		 *  最新版本号
		 */		
		public var latestVersionNumber:String;
		
		/**
		 * 最新版本符 
		 */		
		public var latestVersionLabel:String;
		
		/**
		 *  从服务器获取的版本描述符信息
		 */		
		public var description:String;
		
		private var _available:Boolean = false;
		private var _airURL:String = null;
		
		//--------------------------------------------------------------------------
		//
		//  Methods
		//
		//--------------------------------------------------------------------------
		
		/**
		 * 检查版本
		 */		
		public function checkVersion():void
		{
			var urlLoader:URLLoader = new URLLoader();
			urlLoader.addEventListener(Event.COMPLETE, urlLoader_completeHandler);
			urlLoader.addEventListener(IOErrorEvent.IO_ERROR, urlLoader_errorHandler);
			urlLoader.load(new URLRequest(updateURL));
		}
		
		/**
		 * 开始更新
		 */		
		public function update():void
		{
			if (!_airURL || !_available)
				return;
			
			var urlLoader:URLLoader = new URLLoader();
			urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
			urlLoader.addEventListener(Event.COMPLETE, air_completeHandler);
			urlLoader.addEventListener(IOErrorEvent.IO_ERROR, urlLoader_errorHandler);
			urlLoader.load(new URLRequest(_airURL));
		}
		
		//--------------------------------------------------------------------------
		//
		//  Event Handlers
		//
		//--------------------------------------------------------------------------
		
		private function urlLoader_completeHandler(e:Event):void
		{
			// local version
			var localXML:XML = FlexGlobals.topLevelApplication.nativeApplication.applicationDescriptor;
			var nss:Namespace = localXML.namespace();
			curVersionNumber = localXML.nss::versionNumber;
			curVersionLable = localXML.nss::versionLabel;
			
			//  version
			var remoteXML:XML = XML(e.target.data);
			var ns:Namespace = remoteXML.namespace();
			latestVersionNumber = remoteXML.ns::versionNumber;
			latestVersionLabel = remoteXML.ns::versionLabel;
			_airURL = remoteXML.ns::url;
			description = remoteXML.ns::description;
			
			// 1.2.3 -> 123
			var nowVersion:String = curVersionNumber.split('.').join('');
			var remoteVersion:String = latestVersionNumber.split('.').join('');
			
			var event:AppUpdateEvent = new AppUpdateEvent(AppUpdateEvent.CHECK_RESULT);
			
			if (Number(nowVersion) < Number(remoteVersion))
				_available = event.available = true;
			else
				_available = event.available = false;
			
			dispatchEvent(event);
		}
		
		private function air_completeHandler(e:Event):void
		{
			var tempFile:File = File.applicationDirectory.resolvePath('update/Main.air');
			var fs:FileStream = new FileStream();
			fs.open(new File(tempFile.nativePath), FileMode.WRITE);
			fs.writeBytes(e.currentTarget.data);
			fs.close();
			
			new Updater().update(tempFile, latestVersionNumber);
		}
		
		private function urlLoader_errorHandler(e:IOErrorEvent):void
		{
			dispatchEvent(new AppUpdateEvent(AppUpdateEvent.ERROR));
		}
		
	}
}